package al.work.httplisten;

import al.work.common.task.TaskThread;
import al.work.common.util.ClassUtils;
import al.work.httplisten.annotation.ControllerPath;
import al.work.httplisten.annotation.MethodPath;
import al.work.httplisten.aop.HttpAspectHandler;

import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;

public class HttpServer {
    private com.sun.net.httpserver.HttpServer server;
    private TaskThread task = null;
    private List<Object> controllers = new ArrayList<>();
    private HttpExceptionHandler handler = new HttpExceptionHandler();
    private HttpAspectHandler aspectHandler = new HttpAspectHandler();

    /**
     * 初始化
     * @param port 端口
     * @param controller 控制器所在包
     * @param aop 异常处理所在包
     * @param threads 线程处理数量
     * @param maxWaitTask 最大等待任务数量
     * @return
     */
    public boolean initialize(Integer port, String controller, String aop, int threads, int maxWaitTask) {
        try {
            task = new TaskThread();
            task.initialize(threads, maxWaitTask, "HttpServer");

            server = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(port), 0);

            handler.initialize(aop);
            aspectHandler.initialize(aop);

            initializeContext(controller);

            server.start();
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 初始化请求路径
     * @param name
     * @throws Exception
     */
    protected void initializeContext(String name) throws Exception {
        Map<Class<?>, ControllerPath> classes = ClassUtils.getAnnotationClasses(name, ControllerPath.class);
        for (Map.Entry<Class<?>, ControllerPath> entry : classes.entrySet()) {

            Class<?> controllT = entry.getKey();
            String contrllPath = entry.getValue().path();
            if (null == contrllPath || contrllPath.trim().equalsIgnoreCase("")) {
                throw new Exception("controller: " + controllT.getName() + " not set controllerPath");
            }

            Object controller = controllT.newInstance();
            controllers.add(controller);

            Map<Method, MethodPath> methods = ClassUtils.getAnnotationMethod(controllT, MethodPath.class);
            for (Map.Entry<Method, MethodPath> entry1 : methods.entrySet()) {

                Method method = entry1.getKey();
                String methodPath = entry1.getValue().path();
                if (null == methodPath || methodPath.trim().equalsIgnoreCase("")) {
                    throw new Exception("controller: " + entry.getKey().getName() + " method: " + method.getName() + " not set methodPath");
                }
                server.createContext(contrllPath + methodPath, new HttpJsonHandler(task, handler, aspectHandler, controller, method));
            }
        }
    }
}
